package demo;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.lang.reflect.Field;
import java.util.Objects;

public class MyLombok {

    public static void main(String[] args) {
        Person person = new Person();
        person.setName("John");
        person.setAge(30);
        System.out.println(person);
    }
    @Getter
    @Setter
    @ToString
    @EqualsAndHashCode
    public static class Person {
        private String name;
        private int age;
    }

    /**
     * 生成 Getter 的注解处理器
     */
    public static class GetterProcessor {
        public static void process(Object obj) throws IllegalAccessException {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Getter.class)) {
                    field.setAccessible(true);
                    String fieldName = field.getName();
                    Object value = field.get(obj);
                    System.out.println("Getting value of " + fieldName + ": " + value);
                }
            }
        }
    }

    /**
     * 生成 Setter 的注解处理器
     */
    public static class SetterProcessor {
        public static void process(Object obj, String fieldName, Object value) throws IllegalAccessException {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.getName().equals(fieldName)) {
                    if (field.isAnnotationPresent(Setter.class)) {
                        field.setAccessible(true);
                        field.set(obj, value);
                        System.out.println("Setting value of " + fieldName + ": " + value);
                    }
                }
            }
        }
    }

    /**
     * 生成 ToString 的注解处理器
     */
    public static class ToStringProcessor {
        public static String process(Object obj) throws IllegalAccessException {
            StringBuilder sb = new StringBuilder();
            sb.append(obj.getClass().getSimpleName());
            sb.append("[");
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(ToString.class)) {
                    field.setAccessible(true);
                    String fieldName = field.getName();
                    Object value = field.get(obj);
                    sb.append(fieldName);
                    sb.append("=");
                    sb.append(value);
                    sb.append(", ");
                }
            }
            sb.delete(sb.length() - 2, sb.length()); // 删除最后的逗号和空格
            sb.append("]");
            return sb.toString();
        }
    }

    /**
     * 生成 EqualsAndHashCode 的注解处理器
     */
    public static class EqualsAndHashCodeProcessor {
        public static boolean equals(Object obj1, Object obj2) throws IllegalAccessException {
            if (obj1 == obj2) {
                return true;
            }
            if (obj1 == null || obj2 == null) {
                return false;
            }
            if (!Objects.equals(obj1.getClass(), obj2.getClass())) {
                return false;
            }
            Field[] fields = obj1.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(EqualsAndHashCode.class)) {
                    field.setAccessible(true);
                    Object value1 = field.get(obj1);
                    Object value2 = field.get(obj2);
                    if (!Objects.equals(value1, value2)) {
                        return false;
                    }
                }
            }
            return true;
        }

        public static int hashCode(Object obj) throws IllegalAccessException {
            int result = 1;
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(EqualsAndHashCode.class)) {
                    field.setAccessible(true);
                    Object value = field.get(obj);
                    result = 31 * result + Objects.hashCode(value);
                }
            }
            return result;
        }
    }
}
